package com.wywah.yunduo.config;

import com.wywah.yunduo.security.handlers.FederatedIdentityAuthenticationSuccessHandler;
import com.wywah.yunduo.security.properties.YunduoSecurityProperties;
import com.wywah.yunduo.security.supports.form.FormLoginConfigurer;
import com.wywah.yunduo.security.supports.password.PasswordUserDetailsAuthenticationProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer;
import org.springframework.security.config.annotation.web.configurers.RequestCacheConfigurer;
import org.springframework.security.web.SecurityFilterChain;

@Configuration(proxyBeanMethods = false)
@EnableWebSecurity
public class WebSecurityConfig {

    private final YunduoSecurityProperties yunduoSecurityProperties;

    /**
     * spring security 默认的安全策略
     * @param http security注入点
     * @return SecurityFilterChain
     * @throws Exception
     */
    @Bean
    SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests(authorizeRequests ->
                authorizeRequests
                        .requestMatchers("/token/*",yunduoSecurityProperties.getLoginEndpoint())
                .permitAll()// 开放自定义的部分端点
                .anyRequest()
                .authenticated())
                .headers(header -> header.frameOptions(HeadersConfigurer.FrameOptionsConfig::sameOrigin)// 避免iframe同源无法登录许iframe
        ).with(new FormLoginConfigurer(yunduoSecurityProperties), Customizer.withDefaults());
        // 处理 UsernamePasswordAuthenticationToken
         http.authenticationProvider(new PasswordUserDetailsAuthenticationProvider());
        return http.build();
    }

    /**
     * 暴露静态资源
     *
     * https://github.com/spring-projects/spring-security/issues/10938
     * @param http
     * @return
     * @throws Exception
     */
    @Bean
    @Order(0)
    SecurityFilterChain resources(HttpSecurity http) throws Exception {
        http.securityMatchers((matchers) -> matchers.requestMatchers("/actuator/**", "/css/**", "/error"))
                .authorizeHttpRequests((authorize) -> authorize.anyRequest().permitAll())
                .requestCache(RequestCacheConfigurer::disable)
                .securityContext(AbstractHttpConfigurer::disable)
                .sessionManagement(AbstractHttpConfigurer::disable);
        return http.build();
    }

    public WebSecurityConfig(YunduoSecurityProperties yunduoSecurityProperties) {
        this.yunduoSecurityProperties = yunduoSecurityProperties;
    }
}
